package com.tegtech.starter.swagger.provider;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

import com.tegtech.starter.swagger.properties.SwaggerProperties;

import io.swagger.annotations.ApiOperation;
import springfox.documentation.RequestHandler;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.Contact;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;

public class DocketProvider {
	
	/**
	 * 创建API
	 */
	public static Docket create(ApiInfoProvider apiInfoProvider) {
		return new Docket(DocumentationType.SWAGGER_2)
				// 是否启用Swagger
				.enable(SwaggerProperties.isEnabled())
				// 用来创建该API的基本信息，展示在文档的页面中（自定义展示的信息）
				.apiInfo(apiInfo(apiInfoProvider))
				// 分组名称
				.groupName(apiInfoProvider.getGroupName())
				.select()
				// 设置哪些接口暴露给Swagger展示
				.apis(selectRequestHandler(apiInfoProvider.getBasePackage()))
				// 过滤路径
				.paths(PathSelectors.any())
				.build()
				// 设置安全模式，swagger可以设置访问token
				.securitySchemes(securitySchemes()).securityContexts(securityContexts()).pathMapping(SwaggerProperties.getPathMapping());
	}
	
	/**
	 * 根据basePackage是否有值选择扫描注解的方式
	 * @param basePackage 若指定了basePackage则仅扫描指定的basePackage api，若未指定则扫描所有有注解的api
	 * @return
	 */
	private static Predicate<RequestHandler> selectRequestHandler(String basePackage) {
		if(basePackage != null && basePackage != "") {
			return RequestHandlerSelectors.basePackage(basePackage);
		}
		return RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class);
	}

	/**
	 * 安全模式，这里指定token通过Authorization头请求头传递
	 */
	private static List<ApiKey> securitySchemes() {
		List<ApiKey> apiKeyList = new ArrayList<ApiKey>();
		apiKeyList.add(new ApiKey("Authorization", "Authorization", "header"));
		return apiKeyList;
	}

	/**
	 * 安全上下文
	 */
	private static List<SecurityContext> securityContexts() {
		List<SecurityContext> securityContexts = new ArrayList<>();
		securityContexts.add(SecurityContext.builder().securityReferences(defaultAuth()).forPaths(PathSelectors.regex("^(?!auth).*$")).build());
		return securityContexts;
	}

	/**
	 * 默认的安全上引用
	 */
	private static List<SecurityReference> defaultAuth() {
		AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
		AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
		authorizationScopes[0] = authorizationScope;
		List<SecurityReference> securityReferences = new ArrayList<>();
		securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
		return securityReferences;
	}
	
	/**
	 * API接口信息
	 * @return
	 */
	private static ApiInfo apiInfo(ApiInfoProvider apiInfoProvider) {
		// 用ApiInfoBuilder进行定制
		return new ApiInfoBuilder()
				// 设置标题
				.title(apiInfoProvider.getModuleName())
				// 描述
				.description(apiInfoProvider.getDescription())
				// 作者信息
				.contact(new Contact(apiInfoProvider.getAuthor(), apiInfoProvider.getUrl(), apiInfoProvider.getEmail()))
				// 版本
				.version(apiInfoProvider.getVersion())
				.build();
	}

}
